# coding=utf-8
# 新闻数据的前期处理主要是对新闻文本进行清洗。
# 对新闻的清洗定义为去除和内容无关的其他字符，如 html 标签，无意义的空白和字符。

import bs4
import re


def __split_lines(text):
    return [line.strip() for line in text.split('\n') if line.strip() != '']


def remove_tags(html):
    """
    移除 html 标签。
    """
    return bs4.BeautifulSoup(html, 'lxml').text


def remove_empty_lines(text):
    """
    去除空白行。
    """
    return '\n'.join(__split_lines(text))


__redundant_patterns = {
    r'，[ ]+': '，',
    r'：[ ]+': '：',
    r'、[ ]+': '、',
    r'[ ]+\(': '(',
    r'[ ]+（': '（',
    r'[ ]+\)': ')',
    r'[ ]+）': '）',
}

__compiled_redundant_patters = {sub: re.compile(p, flags=re.M) for p, sub in __redundant_patterns.items()}


def remove_redundant_empty(text):
    """
    处理中文文本中不正常的中断。
    """
    for r, p in __compiled_redundant_patters.items():
        text = p.sub(r, text)
    return text


__sentence_pattern = re.compile(r'[^@\n\t\r。？?;；！!]+?[。？！?!；;]', flags=re.M)


def retain_meaningful_sentences(text, use_len_filter=False, len_range=(7, 200)):
    """
    只保留完整有意义的句子。实现的方法是通过正则表达式去匹配，但是无法解决句子嵌套的问题。
    考虑到句子嵌套的情况在新闻中很少，这种方法可也够用。
    """
    result = re.findall(__sentence_pattern, text)
    if not use_len_filter:
        return '\n'.join(result)
    return '\n'.join([e for e in result if len_range[0] <= len(e) <= len_range[1]])


def get_paragraphs(html, min_sentences=2):
    """
    获取 web 文本中的段落。
    """
    paragraphs = []
    soup = bs4.BeautifulSoup(html, 'lxml')
    for p in soup.find_all('p'):
        p_text = p.get_text().strip()
        if 15 < len(p_text) < 30:
            paragraphs.append(p_text)
            continue
        p_text = retain_meaningful_sentences(remove_empty_lines(p_text), use_len_filter=True).strip()
        if p_text != '' and len(p_text.split('\n')) >= min_sentences:
            paragraphs.append(p_text.strip())
    return paragraphs


def process_peculiar_string(text):
    """
    处理一些奇怪的字符串。
    """
    text = text.replace('\xa0', ' ')  # \xa0 是不间断空白符 &nbsp;
    text = text.replace('\u3000', ' ')  # \u3000 是全角的空白符
    return text


def convert2simplified(text):
    """
    将繁体字转化为简体字。
    """
    try:
        from hanziconv import HanziConv
        return HanziConv.toSimplified(text)
    except ImportError:
        return text


def lowercase(text):
    """
    将英文都转为小写。
    """
    return text.lower()


def process_html(html):
    return remove_redundant_empty(remove_empty_lines(remove_tags(html)))


# 定义新闻中引起公司识别错误的模式
EXCLUDE_PATTERNS = re.compile(
    # 新闻或者图片的媒体来源影响新闻关联公司
    r'[\w]{0,5}声明[:：].+?\s*$|'  # 声明:该文观点仅代表作者本人,搜狐号..
    r'来[源|自][:：@][\w]{2,5}|'  # (来源:新京报)
    r'据[\S]+?[\w]*月[\w]*日报道|'  # 据香港《南华早报》网站9月6日报道
    r'【[\w]+?网综合报道】|'  # 【观察者网综合报道】
    r'据[\w]{2,10}报道|'  # 据澎湃新闻报道，
    r'[\w]{2,5}研报[显示|称]{1,2}|'  # 中信证券研报显示
    r'[\w]{2,10}记者 [\w]{2,10}|'  # 澎湃新闻记者 anyone
    r'[\w]{2,10} 文/[\w]{2,5}|'  # 搜狐科技 文/林国振
    r'[\S]{2,20}[\w]*?月[\w]*?日讯|'  # 网易财经9月4日讯 荣盛发展晚间公告
    r'[\w]{2,10}[\w]*?月[\w]*?日报道|'  # 网易娱乐9月4日报道 荣盛发展..
    r'返回[\s\S]{2,10}查看更多|'  # 返回搜狐，查看更多
    r'[(（]文[/|][\S\s]{2,5}[)）]|'  # (文/某某某)
    r'[(（][\S\s]{2,5}[/|]文[)）]|'  # (某某某/文)
    r'[(（][\S]{2,12}出品 未经许可严禁转载[)）]|'
    r'[(（][\w]{2,5}原创稿件[)）]|'
    r'^[\S]{1,10}[/|][\S]{1,5}\s*$|'  # 搜狐科技/黄阳
    r'来源[\s][/@|][\s][\w]{2,10}|'  # 来源 | 搜狐新闻
    r'^文/[\w]{2,10}]|'  # 文/某某某
    r'[(（][\w]{2,10} [\S]{1,5}发自[\w]{2,10}[)）]|'
    r'^[\w]{2,10}媒体平台$|'  # 搜狐媒体平台
    r'[\S]+?也能找到我们[!！]\s*$|'  # 汽车头条、知乎专栏、米车生活也能找到我们!
    r'[(（][\w]{2,5}[ ]+[\w]{2,5}[)）]|'  # (搜狐体育 译神闲)
    r'[\S]{2,10}内容运营 出品|'
    r'[(（]综合自[:：][\S]+?[)）]|'  # (综合自:证券日报、搜狐科技、中国企业家)
    r'[\w]{2,10}将相关内容整理如下|'  # 搜狐国富智库将相关内容整理如下
    r'转自[:：][\w]{2,10}|'  # 转自:搜狐
    r'[(（][\w]{2,10}讯[)）]|'  # (搜狐体育讯)
    r'^[\w]{2,5}讯[ ,，]|'  # 新浪财经讯 text
    r'^[\w]{2,5}网[讯电]|'  # 正义网[讯电]
    r'[\S]+讯 |'  # 中安在线、中安新闻客户端讯 text
    r'[\S]{2,15}[严禁|不得]转载|'  # (搜狐体育独家出品,严禁转载) 版权所有,未经许可不得转载
    r'本网\S+?所刊载内容之知识产权为\S+?\s*$|'  # 本网(平台)所刊载内容之知识产权为四川新闻网传媒(集团)股份有限公司及/或相关权利人专属所有或持有。
    r'未经[\S]+?授权\S+?不得\S+?[转|登]载\S+?\s*$|'  # 未经人民网股份有限公司及/或相关权利人书面授权,任何单位及个人不得将《人民日报》(电子版)所登载
    r'未经许可\S+?转载\S+?\s*$|'  # 未经许可,禁止进行转载、摘编、复制及建立镜像等任何使用。
    r'本文[\S]{2,15}出品|'  # 本文为《近观》搜狐号出品
    r'本文来源于\S+?\s*$|'  # 本文来源于会计网(http://www.kuaiji.com/),若想了解更多会计政策
    r'分享到[：:].+?\s*$|'  # 分享到: 新浪微博 腾讯微博 网易微博 搜狐微博 人人网 豆瓣 更多
    r'图[片]*[素材]*[均]*来源[于为]*[ ]*[\w]{2,5}|'  # 图片来源于视觉中国
    r'图[片]*[素材]*[均]*[来源]*自[ ]*[\w]{2,5}|'  # 图片均来自于视觉中国
    r'来源[/|@ ][\w]{2,5}|'  # 来源/视觉中国
    r'源自[:：@ ][\w]{2,5}|'  # 图片源自:视觉中国
    r'图[/|@][\w]{2,5}|'  # 图/视觉中国
    r'[配]*图[\s]*[片]*[ ]*[/|@:：][ ]*[\w]{2,5}|'  # 资料图片/视觉中国
    r'图[:：@][\w]{2,5}|'  # (标题图:视觉中国)
    r'[|/]\s*[\w]{2,5}\s*$|'  # 滞留当地的游客则前往机场希望尽快逃离 | 视觉中国
    r'[\w]{2,5} 资料[图]*\s*|'  # 视觉中国 资料图 
    r'图源[\w]{2,5}\s*$|'  # 图源视觉中国
    r'@[\w]{2,5}\s*$|'  # @视觉中国
    r'[\w]{2,5}[\s]*图\s*$|'  # 视觉中国 图
    r' [\w]{2,5}[\s]+图|'  # 视觉中国 图
    r'[\w]{2,5}[\s]*图 |'  # 视觉中国 图 text
    r'[\S]+?未经允许禁止转载[。！?？;；]*\s*$|'  # 注:图片来自中国体育、视觉中国,未经允许禁止转载。
    r'[\w]{2,5}[ ]*供图\s*$|'  # 视觉中国 供图
    r'[\w]{2,5}供图[。 ]+|'  # 视觉中国供图。
    r' 图[\w]{2,5}\s*$|'  # 图视觉中国
    r'图[\s]*[片]* [\w]{2,5}|'  # 图片 视觉中国
    r'来源[:：|][\S]+等|'  # 来源|羊城派综合央视新闻、新华社等
    r'[(（][\w]{2,5}/图[文]*[)）]|'  # (视觉中国/图)
    r'[(（]图[\s]*[/@:：][\s]*[\w]{2,5}[)）]|'  # (图/视觉中国)
    r'作者[：:][ ]*[\w]{2,5}|'  # 作者:视觉中国
    r'[本文]*[授受权]*转载自[\S]+[\s]*$|'  # 本文受权转载自text
    r'编辑[ ]*[：:@|/][ ]*[\w]{2,5}|'  # 编辑:搜狐某人
    r'素材[ ]*[|:：@/][ ]*[\w]{2,5}|'  # 素材 | 南大化院
    r'原文刊载于[\w]{2,5}|'  # 原文刊载于
    r'据[\w]{2,5}消息|'  # 据搜狐音乐消息
    r'[\w]{2,10}编辑从[\w]{2,10}了解到|'  # 搜狐汽车上海编辑从上海起亚经销商处了解到
    r'[\w]{2,10}[\w]月[\w]日电|'  # 人民网北京9月7日电
    r'[\w]{2,5}报道称|'  # 人民网报道称
    r'^新浪体育[:：]|'  # 新浪体育:text
    r'[\[（(【][\w]{2,5}讯 [\w]+?[】)）\]]|'  # 【网易智能讯 9月14日消息】
    r'[\[（(【].+?消息[】)）\]]|'  # 【网易智能讯 9月14日消息】
    r'[\[（(【].*?作者 .*?[】)）\]]|'  # 【观察者网专栏作者 徐小吉】
    r'^本文[由系].+?[\s]*$|'  # 本文系
    r'^文章内容系.+?[\s]*$|'  # 文章内容系
    r'[凡]{0.1}来源为[\w]+?的内容|'  # 凡来源为亿欧网的内容,其版权均属北京亿欧网盟科技有限公司所有。
    r'版权均属[\w]+?所有|'  # 凡来源为亿欧网的内容,其版权均属北京亿欧网盟科技有限公司所有。
    r'[\w]{2,5} [\w]{2,4} 摄\s|'  # 新华网 崔楠 摄
    r'据[\w]+?记者了解|'  # 据第一财经记者了解
    r'注[:：].+?仅供参考.*?[\s]*$|'
    r'如有\S+?版权等问题\S+?请联系\S+?$|'  # 如有文章内容、版权等问题,请联系上游新闻。
    r'\w+?消息\(记者 \w+?\)|'  # 四川在线消息(记者 吴忧)
    # 企查查和天眼查
    r'(企查查|天眼查|启信宝)(资料|数据|\S{0,5}信息|上|APP|app|App)*(显示|获悉)|'  # 企查查资料显示
    r'(据|通过)(查询)*(企查查|天眼查|启信宝)|'  # 根据企查查
    r'(企查查|天眼查|启信宝)(查询|搜索)|'
    r'(信息|数据|图片)来源[:：](企查查|天眼查|启信宝)|'
    # 举列子提到其他公司，影响新闻关联公司。
    r'[例比]如[\S]+?[。；;!！？?]|'  # 例如,上半年招商蛇口布局新业态。
    r'打个比方[\S]+?[。；;!！？?]|'  # 打个比方就拿饿了么来说吧,追根溯源,“上海拉扎斯信息科技有限公司”才是它的本体,因此与其关心注册的问题,还不如好好关注威马品牌所展现的产品品质更为妥当。
    # 某些信息来源
    r'本文来自微信公众号[:：@].+?[\s]*$|'  # 本文来自微信公众号:
    r'关注公众号\S+?\s*$|'  # 关注公众号【学会计有方法】,后台回复“流程”,获取..
    r'根据[\S]+?的报告[,，]|'  # 根据第一财经商业数据中心和阿里巴巴集团旗下B2C在线零售平台天猫的报告,
    r'据[\w]{1,10}数据显示|'  # 据网贷之家数据显示
    r'来自 美食天下.+?的作品。|'  # 来自 美食天下 做个吃货就好 的作品。
    r'\(id:[\S]+?\)|'  # (id:malayutou001)
    r'\([\S]*微信号:[\S]+?\)|'  # (报料微信号:shangyounews)
    r'\(公众号ID:[\S]+?\)|'  # 数据(公众号ID:tuli_shuju)梳理发现
    # 去除网址等
    r'https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+|'
    r'·|'
    # 一行都是无意义的字符
    r'^\W+$|'  # ..
    # 括号内无内容
    r'[<(（【{\[][\]}】)）>]|'
    # 和主题无关的内容
    r'大家好,欢迎来到小华新视界!|'  # 关联到华新视界
    r'[【]温馨提示[】].+?[\s]*$|'
    r'[【]免责声明[】].+?[\s]*$|'
    r'【慎重声明】.+?[\s]*$|'
    r'【特别提醒】.+?[\s]*$|'
    r'干货:手把手教你抓下一只德新交运!|'  # 在某些新闻中经常出现，暂时通过这种方式去除
    r'扫描下方二维码.+?[\s]*$|'
    r'^[\w]{2,5}温馨提示|'  # 新浪教育温馨提示,出分后这三件事最重要:
    r'文章观点仅代表.+?[。？！；;]|'
    r'^小编提醒[:：].+?[\s]*$|'
    r'^官方微博[:：].+?[\s]*$|'
    r'关注[\w]+公众号|'  # 关注网易智能公众号(smartman163)
    r'[(（【\[]公众号[:：].+?[)）】\]]|'  # (公众号：text)
    r'[\w]{2,5}仅提供信息发布平台[。.]*$|'  # 网易仅提供信息发布平台。
    r'欢迎向[\w]+?举报|'  # 欢迎向亿欧举报
    r'来自[\w]+?的数据显示|'  # 来自中国外汇交易中心的数据显示
    r'新京报讯|'
    r'新京报快讯|'
    r'据新京报透露|'
    r'新京报[:：]|'
    r'《\w+?》报道|'
    r'《\w+?》消息|'
    r'新京报记者|'
    r'财经_理财_黄金_外汇_股票_基金_功夫财经网|'
    r'此稿由网友上传至华声在线投诉直通车,记者正在进一步调查核实中,未经华声在线许可,严禁转载。|'
    r'本文素材资料\w*来源于[\S]+$|'
    r'^时光网讯|'
    r'^智通财经APP讯|'
    r'更多港股重磅资讯,下载智通财经app|'
    r'APP市场搜索“中关村在线”,客户端阅读体验更好。|'
    r'^来源链接:http://\S*$|'
    r'本文为作者授权发布,不代表移动支付网立场,转载请注明作者及来源。|'
    r'移动支付网诚邀各位业内人士\S*$|'
    r'欢迎您联系移动支付网主编.*$|'
    r'各式合作意向,请发邮件到.*$|'
    r'活动链接:http://\S*$|'
    r'本网.*所刊载内容之知识产权为\S*专属所有或持有.*$',
    flags=re.M)


def remove_problem_patterns(news):
    """
    去除掉新闻中引起公司绑定错误的内容模式。一般是和新闻主体内容无关的信息。
    """
    return EXCLUDE_PATTERNS.sub('', news + '\n')


def process_news(news, only_sentence=True, do_lowercase=True):
    if only_sentence:
        if do_lowercase:
            return lowercase(remove_problem_patterns(retain_meaningful_sentences(process_html(news))))
        return remove_problem_patterns(retain_meaningful_sentences(process_html(news)))
    if do_lowercase:
        return lowercase(remove_problem_patterns(process_html(news)))
    return remove_problem_patterns(process_html(news))
